<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  <script>
    $(function(){
      // 事件驱动
      var $search = $('.search'),
          $input = $search.find('.search-input'),
          $btn = $search.find(".search-btn"),
          $form = $search.find('.search-form')
          $layer = $search.find('.search-layer');

      // 验证
      $form.on('submit', function(){
        if($.trim($input.val()) === ''){
          return false;
        }
      })
      // 自动完成 Input只要内容改变 其他键不触发 粘贴会触发
      $input.on("input", function(){
        $.ajax({
          url:'https://www.taobao.com?id=1&q=' + encodeURIComponent($.trim($input.val())),
          dataType: 'jsonp'
        }).done(function(data){
          // 异步的方式避免回调
          var html = '',
              dataNum = data['result'].length,
              maxNum = 10;
          if(dataNum === 0){
            $layer.hide().html("")
            return
          }
          for(var i = 0; i<data['result'].length; i++){
            if(i >= maxNum) break
            html += '<li>'+data['result'][i][0]+'</li>'
          }
          $layer.html(html).show()
        }).fail(function(){
          $layer.html('').hide()
        }).always(function(){

        })

      })

      // 事件代理，利用事件冒泡特性，只需要给父类绑定事件 blur按下鼠标触发，click松开鼠标触发
      $layer.on('click', ".search-layer-item", function(){
        $input.val($(this).html())
        $input.parents('form').submit()
      })

      function clickfunc(e){
        var e = e || window.event
        var oli = e.srcElement || e.target
        if(oli.nodeName.toLowerCase() === 'li'){
          console.log('children click')
        }
      }
      function removeHtmlTags(str){
        return str.replace()
      }

    })
  </script>
  <script>
    // 使用面向对象的方式 有两大功能，提交，自动完成
    (function($){
      'use strict';
      

      // 数据缓存
      var cache = {
        data: {},
        count: 0,
        addData: function(key, data){
          if(!this.data[key]){
            this.data[key] = data
            this.count++
          }
        },
        readData: function(key){
          return this.data[key]
        },
        deleteDataByKey: function(key){
          delete this.data[key]
          this.count--
        },
        deleteDataByOrder: function(num){
          var count = 0
          for(var p in this.data){
            if(count >= num){
              break;
            }
            count++
            this.deleteDataByKey(p)
          }

        }
      }




      function Search(el, options){
        this.$el = $(el)
        this.options = options

        this.$input = this.$el.find('.search-input')
        // this.$btn = this.$el.find(".search-btn"),
        this.$form = this.$el.find('.search-form')
        this.$layer = this.$el.find('.search-layer')

        // 提交
        this.$el.on("click", '.search-btn', $.proxy(this.submit))
        if(this.options.autocomplete){
          this.autocomplete()
        }
      }
      Search.DEFAULTS = {
        autocomplete:false,
        url: ''
      }

      Search.prototype.submit = function(){
        if($.trim(this.$input.val()) === ''){
          return false;
        }
        this.$form.submit()
      }
      Search.prototype.autocomplete = function(){
        var timer = null,
            self = this;
        this.$input
            .on('input', function(){
              clearTimeout(timer)
              timer = setTimeout(function(){
                self.getData();
              }, 200)
            })
            .on('focus', $.proxy(this.showLayer, this))
            .on('click', function(){
              return false
            })
        
        this.$layer.showHide(this.options)
        $(document).on('click', $.proxy(this.hideLayer, this))
      }
      Search.prototype.getData = function(){
        var self = this
        var inputVal = self.getInputVal()
        if(cache.readData(inputVal)) return self.$el.trigger('search-getData', [cache.readData(inputVal), self.$layer])
        if(this.jqXHR) this.jqXHR.abort()
        this.jqXHR = $.ajax({
          url: this.options.url + inputVal,
          dataType: 'jsonp'
        }).done(function(data){
          cache.addData(inputVal, data)
          self.$el.trigger('search-getData', [data, self.$layer])
        }).fail(function(){
          self.$el.trigger('search-noData', [self.$layer])
        }).always(function(){
          this.jqXHR = null
        })
      }
      Search.prototype.showLayer = function(){
        if(this.$layer.children().length === 0) return;
        this.$layer.showHide('show')
      }
      Search.prototype.hideLayer = function(){
        this.$layer.showHide('hide')
      }

      $.fn.extend({
        search:function(option){
          return this.each(function(){
            var $this = $(this),
                search = $this.data('search'),
                options = $.extend({}, Search.DEFAULTS, $this.data(), typeof option === 'object' && option);
            
            if(!search){
              $this.data('search', search = new Search($this, options))
            }

            if(typeof search[option] === 'function'){
              search[option]()
            }
          })
        }
      })
    })(jQuery);
  </script>
</body>
</html>